﻿/*
  Name: GPS module RS232 communication library
  Copyright: 
  Author: JackyCA.Liu
  Date: 19/07/11 09:34
  Description: 
*/

#include <StdAfx.h>
#include <stdio.h>
#include <Windows.h>
#include <conio.h>
#include <string.h>

#include "rs232.h"
#include "rs232_util.h"
#include "checksum.h"


void ReadData()
{
    DWORD    dwEv;
    DWORD    dwRead = BLOCK_SIZE;
    DWORD   lpNumberOfBytesRead;
    BYTE    input[BLOCK_SIZE];
    
    BYTE baGetBuf[512]={};
    BYTE forPrint[512]={};
    int CurrentLocation=0;
    
    int match_num=0;
    BYTE match_seperateStr[] = {0x0D, 0x0A, 0x24};
    while (1){
        WaitCommEvent(hComm, &dwEv, NULL);
        if (dwEv == EV_RXCHAR){
            if (!ReadFile(hComm, &input, dwRead, &lpNumberOfBytesRead, &osReader)){
                printError("Read Error");
                break;
            }
            int i_input=0;//for iteration
            for(i_input = 0; i_input<lpNumberOfBytesRead; i_input++){   
              if(matchByte(input[i_input], &match_num, 3, match_seperateStr)) {//pattern matched
                  putData(forPrint, baGetBuf, CurrentLocation);
				  parseData(forPrint, CurrentLocation);
                  printLine(forPrint, &CurrentLocation);
                  putSingleByte(&baGetBuf[CurrentLocation],&input[i_input],&CurrentLocation);
              }else{
                  putSingleByte(&baGetBuf[CurrentLocation],&input[i_input],&CurrentLocation);
              }        
            }
        }
    }
}
long WriteData(char *str) {
	DWORD dwWrite;
	BYTE *ByteCommand = NULL;
	int section_num = generateCommand(str,&ByteCommand);
	if (!WriteFile(hComm, ByteCommand, section_num, &dwWrite, &osReader)){
		return GPS_ERROR_WRITE;//write error
	}
	free(ByteCommand);
}

long GPSInitialize(struct _SerialConfig Serialconfig){
    osReader.hEvent = CreateEvent(NULL, true, false, NULL);
	if(osReader.hEvent == NULL){
		return GPS_ERROR_CREATE_EVENT;//fail to create event
	}
    //##################################################
    // Creating a port handle
    //##################################################
	hComm = CreateFile( _TEXT(Serialconfig.portName),  
						GENERIC_READ | GENERIC_WRITE, 
						0, 
						0, 
						OPEN_EXISTING,
						FILE_FLAG_OVERLAPPED,
						0);
	if (hComm == INVALID_HANDLE_VALUE){
		return GPS_ERROR_OPEN_PORT;//Error opening port
	}
	//##################################################
	// Get current configuration of serial communication port.
	//##################################################
	DCB dcb = {0};
    if (GetCommState(hComm,&dcb) == 0){
       return GPS_ERROR_GET_CONFIG;//Get configuration port has problem
    }
    //##################################################
    // Assign user parameter
    //##################################################
    dcb.BaudRate = Serialconfig.BaudRate;  // Current baud rate (default = 9600)
	dcb.ByteSize = Serialconfig.ByteSize;  // Number of bits/byte, 4-8 (default = 8)
	dcb.Parity = Serialconfig.Parity;      // 0-4= no, odd, even, mark, space (default = 0)
	dcb.StopBits = Serialconfig.StopBits;  // 0,1,2 = 1, 1.5, 2 (default = 0)
    //##################################################
    // Storing a configuration
    //##################################################
    if (SetCommState(hComm,&dcb) == 0){
		return GPS_ERROR_SET_CONFIG;//Set configuration port has problem
    }
    //##################################################
    // Setting communication events mask
    //##################################################
    EvWait = EV_RXCHAR | EV_TXEMPTY;//Using Communication Events
	//EV_RXCHAR - A character was received and placed in the input buffer.
	//EV_TXEMPTY - The last character in the output buffer was sent.
    if (SetCommMask(hComm,EvWait) == 0){
        return GPS_ERROR_SET_EVEN_MASK;//Set even mask Error
    }
    //################################################## 
    // setup device buffer
    //##################################################
    if(SetupComm(hComm, INPUT_BUFFER_SIZE, OUTPUT_BUFFER_SIZE) == 0){
		return GPS_ERROR_SET_COMM;//Fail to initializes the communications parameters
	}
    //##################################################
    // purge any information in buffer
    //##################################################
    if(PurgeComm(hComm, PURGE_TXABORT | 
                         PURGE_RXABORT | 
                         PURGE_TXCLEAR | 
                         PURGE_RXCLEAR)  == 0){
		return GPS_ERROR_PURGE_BUFFER;//purge communication buffer error
	}
    //##################################################
    // Setting a Time-Out communication
    //##################################################
    COMMTIMEOUTS timeouts={0};
	timeouts.ReadIntervalTimeout=Serialconfig.ReadIntervalTimeout;
    timeouts.ReadTotalTimeoutConstant=0;
    timeouts.ReadTotalTimeoutMultiplier=0;
    
    timeouts.WriteTotalTimeoutConstant=0;
    timeouts.WriteTotalTimeoutMultiplier=1;
    if(SetCommTimeouts(hComm, &timeouts) == 0){
		return GPS_ERROR_SET_COMM_TIMEOUTS;//error occureed. Inform user
    }   
	//##################################################
    // Open read thread
    //##################################################
	hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ReadData, NULL, 0, &dwThread);
	if(hThread == NULL) {
		return GPS_ERROR_THREAD;//Fail to open thread
	}
	return GPS_ERROR_SUCCESS;
}

long GPSDeinitialize(){
	if(CloseHandle(hComm) == 0){   // Call this function to close port.
		return GPS_ERROR_CLOSE_PORT;//Fail to close port
	}
	if(CloseHandle(hThread) == 0){
		return GPS_ERROR_CLOSE_THREAD;//Fail to close thread
	}
	return GPS_ERROR_SUCCESS;
}

void DefaultConfig(struct _SerialConfig *Serialconfig) {
	strcpy(Serialconfig->portName, COM_PORT_5);
    Serialconfig->BaudRate = BAUD_RATE_DEFAULT;
	Serialconfig->ByteSize = BYTE_SIZE_DEFAULT;
    Serialconfig->Parity   = PARITY_DEFAULT;
    Serialconfig->StopBits = STOP_BITS_DEFAULT;
	Serialconfig->ReadIntervalTimeout = READ_INTERVAL_TIMEOUT_DEFAULT;
}

void GPSGetLibVersion(struct _LibVersion *LibVersion) {
	LibVersion->major = GPS_LIB_VERSION_MAJOR;
	LibVersion->minor = GPS_LIB_VERSION_MINOR;
	LibVersion->build = GPS_LIB_VERSION_BUILD;
}

int main(){
	struct _SerialConfig Serialconfig;
	DefaultConfig(&Serialconfig);
    GPSInitialize(Serialconfig);

    
    
    while (1)
    {
        char command = getch();
		char str1[] = "06 09 0D 00 FF FF 00 00 00 00 00 00 FF FF 00 00 07";
		char str2[] = "06 01 08 00 F0 00 00 00 00 00 00 00";

		char dis1[] = "06 01 08 00 F0 00 00 00 00 00 00 00";
		char dis2[] = "06 01 08 00 F0 01 00 00 00 00 00 00";
		char dis3[] = "06 01 08 00 F0 02 00 00 00 00 00 00";
		char dis4[] = "06 01 08 00 F0 03 00 00 00 00 00 00";
		char dis5[] = "06 01 08 00 F0 04 00 00 00 00 00 00";
		char dis6[] = "06 01 08 00 F0 05 00 00 00 00 00 00";
        switch(command){
			case 'c':
				WriteData(str1);//reset
				break;
			case 'a':
				WriteData(dis1);
				break;
			case 's':
				WriteData(dis2);
				break;
			case 'd':
				WriteData(dis3);
				break;
			case 'f':
				WriteData(dis4);
				break;
			case 'g':
				WriteData(dis5);
				break;
			case 'h':
				WriteData(dis6);
				break;
			case 'q':
				GPSDeinitialize();
				system("pause");
				return 0;
				break;
			default:
				break;
        }
    }
}